home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / examples / demo / demosrc / d_heart.pro < prev    next >
Text File  |  1997-07-08  |  34KB  |  1,056 lines

  1. ;
  2. ;  Copyright (c) 1997, Research Systems, Inc. All rights reserved.
  3. ;       Unauthorized reproduction prohibited.
  4. ;
  5. ;+
  6. ;  FILE:
  7. ;       d_heart.pro
  8. ;
  9. ;  CALLING SEQUENCE: d_heart
  10. ;
  11. ;  PURPOSE:
  12. ;       Display an animation of a beating heart
  13. ;
  14. ;  MAJOR TOPICS: Animation and widgets
  15. ;
  16. ;  CATEGORY:
  17. ;       IDL 5.0
  18. ;
  19. ;  INTERNAL FUNCTIONS and PROCEDURES:
  20. ;       pro win3d_event         - Handle viewing area events
  21. ;       fun axis3d-event        - Handle the 3-D axis event
  22. ;       pro xdispFile_evt       - Quit the application
  23. ;       pro hea_killEvent           - Handle the kill event
  24. ;       pro menu_event          - Handle the QUIT and INFO events
  25. ;       pro Option_event        - Handle menu bar options events
  26. ;       pro d_heart_event       - Handle heart events (left column)
  27. ;       pro d_Heart_Cleanup     - Cleanup
  28. ;       pro d_heart             - Main procedure
  29. ;
  30. ;  EXTERNAL FUNCTIONS, PROCEDURES, and FILES:
  31. ;       heart.txt
  32. ;       heart.tip
  33. ;       heart.sav               - Data file
  34. ;       pro trackball__define.pro - Create a trackball object
  35. ;       pro gettips.pro         - Read the top file
  36. ;       pro widtips.pro         - Create the tip widgets
  37. ;       pro sizetips.pro        - Size the tip widgets
  38. ;
  39. ;  REFERENCE: IDL Reference Guide, IDL User's Guide
  40. ;
  41. ;  NAMED STRUCTURES:
  42. ;       none.
  43. ;
  44. ;  COMMON BLOCS:
  45. ;       none.
  46. ;
  47. ;  MODifICATION HISTORY:
  48. ;       WRITTEN, SDG, RSI, DEC, 1996.
  49. ;
  50. ;-------------------------------------------------------
  51. ;
  52. ;  PURPOSE : Handle rotations, quit on any button except left.
  53. ;
  54. pro win3d_event,  $
  55.     sEvent      ;  IN: event structure
  56.  
  57.     WIDGET_CONTROL, sEvent.id, GET_UVALUE=UVALUE, /NO_COPY
  58.  
  59.     WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  60.  
  61.     ;  Expose.
  62.     ;
  63.     if (sEvent.type EQ 4) then begin
  64.         state.oWindow->Draw, state.oView
  65.     endif
  66.  
  67.     ;  Handle trackball update
  68.     ;
  69.     bHaveTransform = state.oTrack->Update(sEvent, TRANSFORM=qmat )
  70.     if (bHaveTransform NE 0) then begin
  71.         state.top3D->GetProperty, TRANSFORM=t
  72.         mt = t # qmat
  73.         state.top3D->SetProperty,TRANSFORM=mt
  74.     endif
  75.  
  76.     ;  Button press event.
  77.     ;
  78.     if (sEvent.type EQ 0) then begin
  79.         state.btndown = 1B
  80.         state.oWindow->SetProperty, QUALITY=state.dragq
  81.         WIDGET_CONTROL, sEvent.id, /DRAW_MOTION
  82.     endif
  83.  
  84.     ;  Button release.
  85.     ;
  86.     if (sEvent.type EQ 1) then begin
  87.         if (state.btndown EQ 1b) then begin
  88.             state.oWindow->SetProperty, QUALITY=2
  89.             state.oWindow->Draw, state.oView
  90.         endif
  91.         state.btndown = 0b
  92.         WIDGET_CONTROL, sEvent.id, DRAW_MOTION=0
  93.     endif
  94.  
  95.     ;  Button motion.
  96.     ;
  97.     if ((sEvent.type EQ 2) and (state.btndown EQ 1b)) then begin
  98.         if (bHaveTransform) then begin
  99.             state.oWindow->Draw, state.oView
  100.         endif
  101.     endif
  102.  
  103.     WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  104. END
  105.  
  106. ;-------------------------------------------------------
  107. ;
  108. ;  PURPOSE : Draw an axis given extents
  109. ;
  110. ;
  111. ;      Exts = [xmin, xmax, ymin, ymax, zmin, zmax]
  112. ;      Exts = [  0     1     2     3    4      5 ]
  113. ;
  114. function axis3d, $
  115.     exts, $       ; IN: extents 
  116.     parent_obj, $ ; IN: parent model
  117.     color1, $     ; IN: Color of x axis
  118.     color2, $     ; IN: Color oa z axis
  119.     color3        ; IN: Color of y axis
  120.  
  121.     xverts = [exts(0), exts(1), 0.0, 0.0, 0.0, 0.0]
  122.     yverts = [0.0, 0.0, exts(2), exts(3), 0.0, 0.0]
  123.     zverts = [0.0, 0.0, 0.0, 0.0, exts(4), exts(5)]
  124.  
  125.     p1 = [2,0,1]
  126.     p2 = [2,2,3]
  127.     p3 = [2,4,5]
  128.  
  129.     axis_obj = OBJ_NEW('IDLgrModel')
  130.  
  131.     axis_x = OBJ_NEW('IDLgrpolyline', xverts, yverts, zverts, $
  132.         POLYLINES=p1, COLOR=color1)
  133.  
  134.     axis_y = OBJ_NEW('IDLgrpolyline', xverts, yverts, zverts, $
  135.         POLYLINES=p2, COLOR=color3)
  136.  
  137.     axis_z = OBJ_NEW('IDLgrpolyline', xverts, yverts, zverts, $
  138.         POLYLINES=p3, COLOR=color2)
  139.    
  140.     ;  Add the parts of the box to the box_obj.
  141.     ;
  142.     axis_obj->Add, axis_x
  143.     axis_obj->Add, axis_y
  144.     axis_obj->Add, axis_z
  145.  
  146.     RETURN, axis_obj
  147.  
  148. end ; axis3d
  149.  
  150. ; -----------------------------------------------------------------------------
  151. ;
  152. ; Purpose: Display the information file
  153. ;
  154. pro XDispFile_evt, $
  155.     sEvent          ; IN: event structure
  156.  
  157.     WIDGET_CONTROL, GET_UVALUE=retval, sEvent.id
  158.  
  159.     if (retval EQ "EXIT") then WIDGET_CONTROL, sEvent.top, /DESTROY
  160. end
  161.  
  162. ; -----------------------------------------------------------------------------
  163. ;
  164. ; Purpose:  Main event handler
  165. ;
  166. pro menu_event, $
  167.     sEvent          ; IN: event structure
  168.  
  169.     WIDGET_CONTROL, sEvent.id, GET_UVALUE=UVALUE
  170.  
  171.     case UVALUE of
  172.  
  173.         'QUIT' : begin
  174.             WIDGET_CONTROL, sEvent.top, /DESTROY
  175.         end ; Case of QUIT
  176.  
  177.         'INFO' : begin
  178.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  179.             if( Xregistered('XDisplayFile') NE 0) then begin
  180.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  181.                 RETURN
  182.             endif
  183.           
  184.             XDisplayFile, filepath("heart.txt", $
  185.                 SUBDIR=['examples','demo','demotext']), $
  186.                 DONE_BUTTON='Done', $
  187.                 TITLE="About Beating Hearts", $
  188.                 GROUP=sEvent.top, WIDTH=54, HEIGHT=14
  189.  
  190.             state.oWindow->Draw, state.oView
  191.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  192.          end   ; of INFO
  193.  
  194.     endcase ; of UVALUE
  195.  
  196. end ; end of menu_event
  197.  
  198. ; -----------------------------------------------------------------------------
  199. ;
  200. ;  Purpose:  Options menu event handler
  201. ;
  202. pro option_event, $
  203.     sEvent          ; IN: event structure
  204.  
  205.     WIDGET_CONTROL, sEvent.id, GET_UVALUE=UVALUE
  206.  
  207.     case UVALUE of
  208.  
  209.         ;  Set shading to flat.
  210.         ;
  211.         'FLAT': begin
  212.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  213.             state.heart_inner->SetProperty, SHADING=0
  214.             state.heart_outer->SetProperty, SHADING=0
  215.             state.heart_bot->SetProperty, SHADING=0
  216.             WIDGET_CONTROL, state.wFlatButton, SENSITIVE=0
  217.             WIDGET_CONTROL, state.wGouraudButton, SENSITIVE=1
  218.             state.oWindow->Draw, state.oView
  219.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  220.         END; Case of FLAT
  221.  
  222.         ;  Set shading to Gouraud.
  223.         ;
  224.         'GOURAUD': begin
  225.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  226.             state.heart_inner->SetProperty, SHADING=1
  227.             state.heart_outer->SetProperty, SHADING=1
  228.             state.heart_bot->SetProperty, SHADING=1
  229.             WIDGET_CONTROL, state.wFlatButton, SENSITIVE=1
  230.             WIDGET_CONTROL, state.wGouraudButton, SENSITIVE=0
  231.             state.oWindow->Draw, state.oView
  232.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  233.         END; Case of GOURAUD
  234.  
  235.         ;  Set style to wire.
  236.         ;
  237.         'WIRE': begin
  238.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  239.             state.heart_inner->SetProperty, STYLE=1
  240.             state.heart_outer->SetProperty, STYLE=1
  241.             state.heart_bot->SetProperty, STYLE=1
  242.             WIDGET_CONTROL, state.wWireButton, SENSITIVE=0
  243.             WIDGET_CONTROL, state.wSolidButton, SENSITIVE=1
  244.             state.oWindow->Draw, state.oView
  245.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  246.         END; Case of WIRE
  247.  
  248.         ;  Set style to solid.
  249.         ;
  250.         'SOLID': begin
  251.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  252.             state.heart_inner->SetProperty, STYLE=2
  253.             state.heart_outer->SetProperty, STYLE=2
  254.             state.heart_bot->SetProperty, STYLE=2
  255.             WIDGET_CONTROL, state.wWireButton, SENSITIVE=1
  256.             WIDGET_CONTROL, state.wSolidButton, SENSITIVE=0
  257.             state.oWindow->Draw, state.oView
  258.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  259.         END; Case of SOLID
  260.  
  261.         ;  Set the drag quality to low.
  262.         ;
  263.         'LOW': begin
  264.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  265.             state.dragq = 0
  266.             WIDGET_CONTROL, state.wDragLowButton, SENSITIVE=0
  267.             WIDGET_CONTROL, state.wDragHiButton, SENSITIVE=1
  268.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  269.         END; Case of LOW
  270.  
  271.         ;  Set the drag quality to high.
  272.         ;
  273.         'HIGH': begin
  274.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  275.             state.dragq = 2
  276.             WIDGET_CONTROL, state.wDragLowButton, SENSITIVE=1
  277.             WIDGET_CONTROL, state.wDragHiButton, SENSITIVE=0
  278.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  279.         END; Case of HIGH
  280.  
  281.     ENDCASE ; of UVALUE
  282.  
  283. END ; end of option_event
  284.  
  285. ; -----------------------------------------------------------------------------
  286. ;
  287. ; Purpose:  Main menu event handler: heart_event
  288. ;
  289.  
  290. pro d_heart_event, $
  291.     sEvent             ; IN: event structure
  292.  
  293.     ;  Quit this application using the close box.
  294.     ;
  295.     if (TAG_NAMES(sEvent, /STRUCTURE_NAME) EQ $
  296.         'WIDGET_KILL_REQUEST') then begin
  297.         WIDGET_CONTROL, sEvent.top, /DESTROY
  298.         RETURN
  299.     endif
  300.  
  301.     WIDGET_CONTROL, sEvent.id, get_UVALUE=UVALUE
  302.  
  303.     case UVALUE of
  304.  
  305.         ;  Reset the initial orientation of the view.
  306.         ;
  307.         'RESET' : begin
  308.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  309.             WIDGET_CONTROL, state.wBase, SENSITIVE=0
  310.             state.top3D->SetProperty, TRANSFORM=state.initTM
  311.             state.oWindow->Draw, state.oView
  312.             WIDGET_CONTROL, state.wBase, SENSITIVE=1
  313.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  314.         END; Case of RESET
  315.  
  316.         ;  Toggle between hiding or showing the outer surface.
  317.         ;
  318.         'OUTER' : begin
  319.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  320.             if (sEvent.select EQ 0) then HIDE=1 else HIDE=0
  321.             state.heart_outer->SetProperty, HIDE=hide
  322.             ; Update the view
  323.             state.oWindow->Draw, state.oView
  324.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  325.         END ; Case of OUTER
  326.  
  327.         ;  Toggle between hiding or showing the inner surface.
  328.         ;
  329.         'INNER' : begin
  330.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  331.             if (sEvent.select EQ 0) then HIDE=1 else HIDE=0
  332.             state.heart_inner->SetProperty, HIDE=hide
  333.             ; Update the view
  334.             state.oWindow->Draw, state.oView
  335.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  336.         END ; Case of INNER
  337.  
  338.         ;  Toggle between hiding or showing the bottom surface.
  339.         ;
  340.         'BOTTOM' : begin
  341.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  342.             if (sEvent.select EQ 0) then HIDE=1 else HIDE=0
  343.             state.heart_bot->SetProperty, HIDE=hide
  344.             ; Update the view
  345.             state.oWindow->Draw, state.oView
  346.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  347.         END ; Case of BOTTOM
  348.  
  349.         ;  Toggle between hiding or showing the 3 axes.
  350.         ;
  351.         'AXIS' : begin
  352.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  353.             if (sEvent.select EQ 0) then HIDE=1 else HIDE=0
  354.             state.axis_obj->SetProperty, HIDE=hide
  355.             ; Update the view
  356.             state.oWindow->Draw, state.oView
  357.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  358.         END ; Case of AXIS
  359.  
  360.         ;  Toggle between hiding or showing the light icons.
  361.         ;
  362.         'LITES' : begin
  363.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  364.             if (sEvent.select EQ 0) then HIDE=1 else HIDE=0
  365.             state.lite1_icon->SetProperty, HIDE=hide
  366.             state.lite2_icon->SetProperty, HIDE=hide
  367.             ; Update the view
  368.             state.oWindow->Draw, state.oView
  369.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  370.         END ; Case of LITES
  371.  
  372.         ;  Toggle between hiding or showing the annotation text.
  373.         ;
  374.         'ANNO' : begin
  375.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  376.             if (sEvent.select EQ 0) then HIDE=1 else HIDE=0
  377.             state.annotation->SetProperty, HIDE=hide
  378.             ; Update the view
  379.             state.oWindow->Draw, state.oView
  380.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  381.         END ; Case of ANNO
  382.  
  383.         ;  Animate the display. Make the heart to beat.
  384.         ;
  385.         'CPR' : begin
  386.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  387.             WIDGET_CONTROL, state.wBase, SENSITIVE=0
  388.             ; Update the view
  389.             i = (state.current_frame + 1) MOD 16
  390.             for j = 0,15 do begin
  391.                 state.heart_inner->SetProperty, $
  392.                     DATA=REFORM(state.i_verts(i,*,*))
  393.                 state.heart_outer->SetProperty, $
  394.                     DATA=REFORM(state.o_verts(i,*,*))
  395.                 state.heart_bot->SetProperty, $
  396.                     DATA=REFORM(state.b_verts(i,*,*))
  397.                 state.oWindow->Draw, state.oView
  398.                 i = (i + 1) MOD 16
  399.             endfor  ;  of  j
  400.             WIDGET_CONTROL, state.wBase, SENSITIVE=1
  401.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  402.         END ; Case of CPR
  403.  
  404.         ;  Show only the next frame.
  405.         ;
  406.         'SKIP' : begin
  407.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=state, /NO_COPY
  408.             WIDGET_CONTROL, state.wBase, SENSITIVE=0
  409.             i = (state.current_frame + 1)  MOD 16
  410.             state.heart_inner->SetProperty, $
  411.                 DATA=REFORM(state.i_verts(i,*,*))
  412.             state.heart_outer->SetProperty, $
  413.                 DATA=REFORM(state.o_verts(i,*,*))
  414.             state.heart_bot->SetProperty, $
  415.                 DATA=REFORM(state.b_verts(i,*,*))
  416.             ; Update the view
  417.             state.oWindow->Draw, state.oView
  418.             state.current_frame = i
  419.             WIDGET_CONTROL, state.wBase, SENSITIVE=1
  420.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=state, /NO_COPY
  421.         END ; Case of SKIP
  422.  
  423.     ENDCASE
  424. END
  425.  
  426. ;-----------------------------------------------------------------
  427. ;
  428. ;    PURPOSE : cleanup procedure. restore colortable, destroy objects.
  429. ;
  430. pro d_heart_Cleanup, wBase
  431.  
  432.     WIDGET_CONTROL, wBase, GET_UVALUE=state, /NO_COPY
  433.  
  434.     ;  Destroy the top objects
  435.     ;
  436.     OBJ_DESTROY, state.oView
  437.     OBJ_DESTROY, state.font18
  438.     OBJ_DESTROY, state.font24
  439.     OBJ_DESTROY, state.font_sm
  440.     OBJ_DESTROY, state.font_big
  441.     OBJ_DESTROY, state.title1
  442.     OBJ_DESTROY, state.title2
  443.     OBJ_DESTROY, state.oTrack
  444.     OBJ_DESTROY, state.oFont
  445.     OBJ_DESTROY, state.oText
  446.     OBJ_DESTROY, state.oContainer
  447.  
  448.     ;  Restore the color table
  449.     ;
  450.     TVLCT, state.colorTable
  451.  
  452.     if widget_info(state.groupBase, /valid) then $
  453.         widget_control, state.groupBase, /map
  454.  
  455. end   ;  of Texture_Cleanup
  456.  
  457.  
  458. ;-----------------------------------------------------
  459. ;
  460. ;  PURPOSE The beating heart main procedure. This application
  461. ;          shows a beating heart.
  462. ;
  463. PRO d_heart, $
  464.     filename=filename, $ ; IN: (opt) data file name
  465.     xdim=xdim, $         ; IN: (opt) x dimension
  466.     ydim=ydim, $         ; IN: (opt) y dimension
  467.     GROUP=group, $       ; IN: (opt) group identifier
  468.     APPTLB = appTLB      ; OUT: (opt) TLB of this application
  469.  
  470.     if (N_ELEMENTS(filename) EQ 0) then filename='heart.sav'
  471.  
  472.     ;  Check the validity of the group identifier
  473.     ;
  474.     ngroup = N_ELEMENTS(group)
  475.     if(ngroup NE 0) then begin
  476.         groupStatus = WIDGET_INFO( group, /VALID_ID)
  477.         if(groupStatus EQ 0) then begin
  478.             print, 'Group leader identifier not valid'
  479.           print, ' Exiting program'
  480.           RETURN
  481.         endif
  482.         groupBase = group
  483.     endif else groupBase = 0L
  484.  
  485.     ;  Get the current color vectors to restore
  486.     ;  when this application is exited.
  487.     ;
  488.     TVLCT, savedR, savedG, savedB, /GET
  489.  
  490.     ; Build color table from color vectors
  491.     ;
  492.     colorTable = [[savedR],[savedG],[savedB]]
  493.  
  494.     ;  Get the screen size.
  495.     ;
  496.     DEVICE, GET_SCREEN_SIZE = screenSize
  497.  
  498.     if (!D.N_COLORS LE 256) then begin
  499.         string = 'This application is optimized for >256 colors'
  500.         res = DIALOG_MESSAGE(string, /INFORMATION)
  501.     endif
  502.  
  503.     if (N_ELEMENTS(xdim) EQ 0) then begin
  504.         xdim = 0.6 * screenSize(0)
  505.     end ; if xdim
  506.  
  507.     if (N_ELEMENTS(ydim) EQ 0) then begin
  508.         ydim = 0.8 * xdim
  509.     endif
  510.  
  511.     ;  Get the tips.
  512.     ;
  513.     sText = getTips(filepath('heart.tip', $
  514.         SUBDIR=['examples','demo', 'demotext']) )
  515.  
  516.     ;  Set debug flag for comments.
  517.     ;
  518.     debug = 1
  519.  
  520.     ;  Create the top level base.
  521.     ;
  522.     if (N_ELEMENTS(group) EQ 0) then begin
  523.         wBase = WIDGET_BASE(/COLUMN, $
  524.             TITLE="Beating Heart", $
  525.             /TLB_KILL_REQUEST_EVENTS, $
  526.             XPAD=0, YPAD=0, $
  527.             TLB_FRAME_ATTR=1, MBAR=mbarbase)
  528.     endif else begin
  529.         wBase = WIDGET_BASE(/COLUMN, $
  530.             TITLE="Beating Heart", $
  531.             XPAD=0, YPAD=0, $
  532.             TLB_FRAME_ATTR=1, MBAR=mbarbase, $
  533.             /TLB_KILL_REQUEST_EVENTS, $
  534.             GROUP_LEADER=group)
  535.     endelse
  536.  
  537.     ;  Create the file|quit button.
  538.     ;
  539.     wFileButton = WIDGET_BUTTON(mbarbase,VALUE = 'File',/Menu)
  540.  
  541.         wQuitButton = WIDGET_BUTTON(wFileButton, $
  542.             VALUE = 'Quit',UVALUE='QUIT', $
  543.             EVENT_PRO='menu_event')
  544.  
  545.     ;  Create the option menu.
  546.     ;
  547.     wOptionButton = WIDGET_BUTTON(mbarbase,VALUE = 'Options',/Menu)
  548.  
  549.         ; Create the Shading Options Button.
  550.         ;
  551.         wShadingButton = WIDGET_BUTTON(wOptionButton, $
  552.             EVENT_PRO='option_event', $
  553.             VALUE = 'Shading',UVALUE='Shading',/MENU)
  554.  
  555.             wFlatButton = WIDGET_BUTTON(wShadingButton, $
  556.                 EVENT_PRO='option_event', $
  557.                 VALUE = 'Flat',UVALUE='FLAT')
  558.  
  559.             wGouraudButton = WIDGET_BUTTON(wShadingButton, $
  560.                 EVENT_PRO='option_event', $
  561.                 VALUE = 'Gouraud',UVALUE='GOURAUD')
  562.  
  563.         ; Create the Style Options Button.
  564.         ;
  565.         wStyleButton = WIDGET_BUTTON(wOptionButton, $
  566.             EVENT_PRO='option_event', $
  567.             VALUE = 'Style',UVALUE='STYLE',/MENU)
  568.  
  569.             wWireButton = WIDGET_BUTTON(wStyleButton, $
  570.                 EVENT_PRO='option_event', $
  571.                 VALUE = 'Wire',UVALUE='WIRE')
  572.  
  573.             wSolidButton = WIDGET_BUTTON(wStyleButton, $
  574.                 EVENT_PRO='option_event', $
  575.                 VALUE = 'Solid',UVALUE='SOLID')
  576.  
  577.         ; Create the Drag Quality Options Button.
  578.         ;
  579.         wDragButton = WIDGET_BUTTON(wOptionButton, $
  580.             EVENT_PRO='option_event', $
  581.             VALUE = 'Drag Quality', UVALUE='DRAG',/MENU)
  582.  
  583.             wDragLowButton = WIDGET_BUTTON(wDragButton, $
  584.                 EVENT_PRO='option_event', $
  585.                 VALUE = 'Low',UVALUE='LOW')
  586.  
  587.             wDragHiButton = WIDGET_BUTTON(wDragButton, $
  588.                 EVENT_PRO='option_event', $
  589.                 VALUE = 'High',UVALUE='HIGH')
  590.  
  591.     ; Create the help|about button.
  592.     ;
  593.     wHelpButton = WIDGET_BUTTON(mbarbase, $
  594.         VALUE='About', /HELP, /MENU)
  595.  
  596.         wAboutButton = WIDGET_BUTTON(wHelpButton, $
  597.             EVENT_PRO = 'menu_event', $
  598.             VALUE = 'About Beating Heart',UVALUE='INFO')
  599.  
  600.     ;  Create the first child of the top level base (wBase).
  601.     ;
  602.     wTopRowBase =  WIDGET_BASE(wBase, Column = 2)
  603.  
  604.         ;  Create a base for the left column.
  605.         ;
  606.         wLeftBase = WIDGET_BASE(wTopRowBase, $
  607.             /BASE_ALIGN_LEFT, Column=1,/Frame)
  608.  
  609.             ;  Create the Object Toggle Area.
  610.             ;
  611.             wObjToggleArea = WIDGET_BASE(wLeftBase, /column, /Frame)
  612.  
  613.                 wObjTogLabel = WIDGET_LABEL(wObjToggleArea, $
  614.                     /align_center, $
  615.                     value='OBJECT VISIBLITY')
  616.  
  617.                 wObjToggleBase = WIDGET_BASE(wObjToggleArea, $
  618.                     /column, /NONEXCLUSIVE)
  619.  
  620.                     wObj1Toggle = WIDGET_BUTTON(wObjToggleBase, $
  621.                         VALUE="Outer Surface", $
  622.                         UVALUE='OUTER', EVENT_PRO='d_heart_event')
  623.  
  624.                     wObj2Toggle = WIDGET_BUTTON(wObjToggleBase, $
  625.                         VALUE="Inner Surface", $
  626.                         UVALUE='INNER', EVENT_PRO='d_heart_event')
  627.  
  628.                     wObj3Toggle = WIDGET_BUTTON(wObjToggleBase, $
  629.                         VALUE="Bottom Surface", $
  630.                         UVALUE='BOTTOM', EVENT_PRO='d_heart_event')
  631.  
  632.                     wObj5Toggle = WIDGET_BUTTON(wObjToggleBase, $
  633.                         VALUE="Axis 3D", $
  634.                         UVALUE='AXIS', EVENT_PRO='d_heart_event')
  635.  
  636.                     wObj6Toggle = WIDGET_BUTTON(wObjToggleBase, $
  637.                         VALUE="Light Icons", $
  638.                         UVALUE='LITES', EVENT_PRO='d_heart_event')
  639.  
  640.                     wObj7Toggle = WIDGET_BUTTON(wObjToggleBase, $
  641.                         VALUE="Annotations", $
  642.                         UVALUE='ANNO', EVENT_PRO='d_heart_event')
  643.  
  644.             ;  Create a Animation buttons.
  645.             ;
  646.             wAnimArea = WIDGET_BASE(wLeftBase, /column, /Frame)
  647.  
  648.                 beat_label = WIDGET_LABEL(wAnimArea, $
  649.                     VALUE="Animation Controls")
  650.  
  651.                 cpr_button = WIDGET_BUTTON(wAnimArea, $
  652.                     VALUE="APPLY CPR", UVALUE='CPR')
  653.  
  654.                 stop_button = WIDGET_BUTTON(wAnimArea, $
  655.                     VALUE="SKIP A BEAT", UVALUE='SKIP')
  656.  
  657.             ;  Create a Transformation Reset button.
  658.             ;
  659.             wResetArea = WIDGET_BASE(wLeftBase, /column, /Frame)
  660.  
  661.                 reset_Label = WIDGET_LABEL(wResetArea, $
  662.                     VALUE="Reset orientation")
  663.                 reset_button = WIDGET_BUTTON(wResetArea, $
  664.                     VALUE="Reset", UVALUE='RESET')
  665.  
  666.         ;  A.Create a base for the right column
  667.         ;
  668.         wRightBase = WIDGET_BASE(wTopRowBase, Column=1, /Frame)
  669.  
  670.             wDraw3D = widget_draw(wRightBase, $
  671.                 XSIZE=xdim, YSIZE=ydim, /BUTTON_EVENTS, $
  672.                 UVALUE='DRAW', RETAIN=0, $
  673.                 EVENT_PRO='win3d_event', /EXPOSE_EVENTS, $
  674.                 GRAPHICS_LEVEL=2)
  675.  
  676.         ;  Create tips texts.
  677.         ;
  678.         wStatusBase = WIDGET_BASE(wBase, MAP=0, /ROW)
  679.  
  680.             nWidgets = 2
  681.             wText = LONARR(nWidgets)
  682.             widTips, wStatusBase, sText.text, XSIZE=36, $
  683.                 YSIZE=3, NWIDGETS=nWidgets, wText
  684.  
  685.     ;  Here, all the wideget has been created, now relaize them.
  686.     ;
  687.     WIDGET_CONTROL, wBase, /REALIZE
  688.  
  689.     ;  Set the state of the buttons.
  690.     ;
  691.     WIDGET_CONTROL, wObj1Toggle, SET_BUTTON=1
  692.     WIDGET_CONTROL, wObj2Toggle, SET_BUTTON=1
  693.     WIDGET_CONTROL, wObj3Toggle, SET_BUTTON=1
  694.     WIDGET_CONTROL, wObj5Toggle, SET_BUTTON=0
  695.     WIDGET_CONTROL, wObj6Toggle, SET_BUTTON=0
  696.     WIDGET_CONTROL, wObj7Toggle, SET_BUTTON=1
  697.  
  698.     ;  Returns the top level base in the appTLB keyword.
  699.     ;
  700.     appTLB = wBase
  701.  
  702.     ;  Size the tips widgets.
  703.     ;
  704.     sizeTips, wBase, wText, wStatusBase
  705.  
  706.     WIDGET_CONTROL, wDraw3D, GET_VALUE=oWindow
  707.  
  708.     ;  Desensitize everything while loading the data.
  709.     ;
  710.     WIDGET_CONTROL, wBase, SENSITIVE=0
  711.  
  712.     ident = [[1.0,0,0,0], $
  713.         [0.0,1,0,0], $
  714.         [0.0,0,1,0], $
  715.         [0.0,0,0,1]]
  716.  
  717.     ;  Define Colors.
  718.     ;
  719.     white = [255,255,255]
  720.     red = [255,0,0]
  721.     green = [0,255,0]
  722.     blue = [0,0,255]
  723.     purple = [255,0,255]
  724.  
  725.     ;  Define the Graphics View.
  726.     ;
  727.     oView = OBJ_NEW('IDLgrView', COLOR=[0,0,0], PROJECTION=1, $
  728.         VIEWPLANE_RECT=[-20,-20,40,40], EYE=21.0, ZCLIP=[20, -20])
  729.  
  730.     ;  Make the text location to be centered.
  731.     ;
  732.     myview = [-20,-20,40,40]
  733.     textLocation = [myview[0]+0.5*myview[2], myview[1]+0.5*myview[3]]
  734.  
  735.     ;  Create and display the PLEASE WAIT text.
  736.     ;
  737.     oFont = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=18)
  738.     oText = OBJ_NEW('IDLgrText', $
  739.         'Starting up  Please wait...', $
  740.         ALIGN=0.5, $
  741.         LOCATION=textLocation, $
  742.         COLOR=[255,255,0], FONT=oFont)
  743.  
  744.  
  745.     aspect = FLOAT(xdim)/FLOAT(ydim)
  746.  
  747.     ; Define top level model.
  748.     ;
  749.     top = OBJ_NEW('IDLgrModel')
  750.  
  751.     top->Add, oText
  752.  
  753.     ;  top3D is the top object for transformable objects.
  754.     ;
  755.     top3D = OBJ_NEW('IDLgrModel')
  756.     top->Add, top3D
  757.  
  758.     ;  Add the top object to the view.
  759.     ;
  760.     oView->Add, top
  761.  
  762.     ;  Draw the starting up screen.
  763.     ;
  764.     oWindow->Draw, oView
  765.  
  766.     ;  Draw the Text and Title.
  767.     ;
  768.     if (screensize(0) LT 800) then begin
  769.         font_sm = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=10. )
  770.         font_big = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=14. )
  771.     endif else begin
  772.         font_sm = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=14. )
  773.         font_big = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=18. )
  774.     endelse
  775.  
  776.     font24 = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=24. )
  777.     font18 = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=18. )
  778.  
  779.     ;  Ceate the annotation.
  780.     ;
  781.     annotation = OBJ_NEW('IDLgrModel')
  782.     top->Add, annotation
  783.  
  784.     title1 = OBJ_NEW('IDLgrText', LOCATION=[-19,-17], $
  785.                    'Data Courtesy of: ', $
  786.                    color=[0,255,0], font=font_sm)
  787.  
  788.     ;  Add Title1 to the Annotation Object.
  789.     ;
  790.     annotation->Add, title1
  791.  
  792.     title2 = OBJ_NEW('IDLgrText', LOCATION=[-19,-19], $
  793.         'Dr. Stephan Nekolla', $
  794.         COLOR=[0,255,0], FONT=font_sm)
  795.  
  796.     ;  Add Title2 to the Annotation Object.
  797.     ;
  798.     annotation->Add, title2
  799.  
  800.     ;  Create the Heart Object.
  801.     ;
  802.     heart = OBJ_NEW('IDLgrModel')
  803.     top3D->Add, heart
  804.  
  805.     ;  Draw the red bounding box.
  806.     ;
  807.     extents = [-40.0, 40.0, -20.0, 20.0, -20.0, 20.0]
  808.     axis_obj = axis3D(extents, top3D, red, green, blue)
  809.     top3D->Add,axis_obj
  810.     axis_obj->SetProperty, HIDE=1
  811.  
  812.     ;  Draw an axis from xmin to xmax etc...
  813.     ;
  814.     extents = [-20.0, 20.0, -20.0, 20.0, -20.0, 0.0]
  815.    
  816.     ;  Define some colors in RGB space.
  817.     ;
  818.     red =   [250, 10,  10]
  819.     green = [10,  250, 10]
  820.     blue =  [10,  10,  250]
  821.  
  822.     ;  Compute the first geometry.
  823.     ;
  824.     case !VERSION.OS_FAMILY of
  825.         'unix' : dirsep = '/'
  826.         else   : dirsep = '\'
  827.     endcase
  828.    
  829.     ;  heart_file = 'data' + dirsep + 'gated_15.sav'
  830.     ;
  831.     heart_file = filepath('heart.sav', $
  832.                 SUBDIR=['examples','demo','demodata'])
  833.     restore, heart_file
  834.  
  835.     ;  Generate the inner layer from the first frame of data.
  836.     ;
  837.     heart_inner = OBJ_NEW('IDLgrPolygon', $
  838.         REFORM(I_VERTS(0,*,*)), $
  839.         polygons=REFORM(I_POLYS(0,*)), $
  840.         SHADING=1, $
  841.         vert_color=REFORM(I_COLOR(0,*,*)))
  842.     heart->Add, heart_inner
  843.  
  844.     ;  Generate the outer layer from the first frame of data.
  845.     ;
  846.     heart_outer = OBJ_NEW('IDLgrPolygon', $
  847.         REFORM(O_VERTS(0,*,*)), $
  848.         polygons=REFORM(O_POLYS(0,*)), $
  849.                SHADING=1, $
  850.         vert_color=REFORM(O_COLOR(0,*,*)))
  851.     heart->Add, heart_outer
  852.  
  853.     ;  Generate the Bottom layer from the first frame of data.
  854.     ;
  855.     heart_bot = OBJ_NEW('IDLgrPolygon', $
  856.         REFORM(B_VERTS(0,*,*)), $
  857.         polygons=REFORM(B_POLYS(0,*)), $
  858.         SHADING=1, $
  859.         vert_color=REFORM(B_COLOR(0,*,*)))
  860.     heart->Add, heart_bot
  861.  
  862.     ;  Get and Set properties on the bounds of the geometry.
  863.     ;
  864.     ;  X Min/MAX for Inner:       18.0476      38.9740
  865.     ;  Y Min/MAX for Inner:       87.8208      108.416
  866.     ;  Z Min/MAX for Inner:       6.42048      22.5585
  867.     ;  X Min/MAX for Outer:       15.0989      43.3261
  868.     ;  Y Min/MAX for Outer:       84.3699      112.872
  869.     ;  Z Min/MAX for Outer:       1.65995      26.6269
  870.     ;  Color Min/MAX:             3.83333      42.5000
  871.     ;
  872.     xr = [18, 40]
  873.     yr = [85, 115]
  874.     zr = [0.0, 30.0]
  875.     cr = [3.8, 42.5]
  876.  
  877.     ; Determine the translation required to fit data within plotview,
  878.     ; and its inverse.
  879.     ;
  880.     xc = -29.0
  881.     yc = -98.0
  882.     zc = -13.0
  883.     heart->translate, xc, yc, zc
  884.  
  885.     ;  Generate the light sources.
  886.     ;
  887.     li_xverts = [-1.0, 1.0, 0.0, 0.0, 0.0, 0.0]
  888.     li_yverts = [0.0, 0.0, 1.0, -1.0, 0.0, 0.0]
  889.     li_zverts = [0.0, 0.0, 0.0, 0.0, 1.0, -1.0]
  890.     li_pl = [2,0,1,$
  891.             2,2,3,$
  892.             2,4,5]
  893.  
  894.     ;  Generate an ambient light source.
  895.     ;
  896.     lite0 = OBJ_NEW('IDLgrLight', TYPE=0, COLOR=[200,200,200])
  897.     top->Add, lite0
  898.  
  899.     ;  Generate the first light source.
  900.     ;
  901.     lite1_icon = OBJ_NEW('IDLgrModel')
  902.     top->Add, lite1_icon
  903.     lite1_icon->SetProperty, HIDE=1
  904.     lite1_x = 19.0
  905.     lite1_y = 19.0
  906.     lite1_z = 10.0
  907.     lite1_icon_pl = OBJ_NEW('IDLgrPolyline', $
  908.         li_xverts, li_yverts, li_zverts,$
  909.         POLYLINES=li_pl, COLOR=white)
  910.  
  911.     lite1_icon->Add,lite1_icon_pl
  912.     lite1_icon->translate, lite1_x, lite1_y, lite1_z
  913.  
  914.     ;  Add a Positional Light type = 1.
  915.     ;
  916.     lite1 = OBJ_NEW('IDLgrLight', $
  917.         LOCATION=[lite1_x, lite1_y, lite1_z], TYPE=1)
  918.     top->Add,lite1
  919.  
  920.  
  921.     ;  Generate the second light source.
  922.     ;
  923.     lite2_icon = OBJ_NEW('IDLgrModel')
  924.     top->Add,lite2_icon
  925.     lite2_icon->SetProperty, HIDE=1
  926.     lite2_x = -19.0
  927.     lite2_y = -19.0
  928.     lite2_z = 10.0
  929.     lite2_icon_pl = OBJ_NEW('IDLgrPolyline', $
  930.         li_xverts, li_yverts, li_zverts,$
  931.         POLYLINES=li_pl, COLOR=white)
  932.     lite2_icon->Add, lite2_icon_pl
  933.     lite2_icon->Translate, lite2_x, lite2_y, lite2_z
  934.  
  935.     ;  Add a Positional Light type = 1.
  936.     ;
  937.     lite2 = OBJ_NEW('IDLgrLight', $
  938.          LOCATION=[lite2_x, lite2_y, lite2_z], TYPE=1)
  939.     top->Add, lite2
  940.  
  941.     ;  Set the current frame.
  942.     ;
  943.     current_frame = 0
  944.  
  945.     ;  Desensitize the current options.
  946.     ;
  947.     WIDGET_CONTROL, wDragLowButton, SENSITIVE=0
  948.     WIDGET_CONTROL, wGouraudButton, SENSITIVE=0
  949.     WIDGET_CONTROL, wSolidButton, SENSITIVE=0
  950.  
  951.     ;  Add the trackball object for interactive change
  952.     ;  of the scene orientation
  953.     ;
  954.     oTrack = OBJ_NEW('Trackball', [xdim/2.0, ydim/2.0], xdim/2.0)
  955.  
  956.     oContainer = OBJ_NEW('IDLgrContainer')
  957.     oContainer->Add, oView
  958.     oContainer->Add, oTrack
  959.  
  960.  
  961.     ; Setup the state structure
  962.     ;
  963.     state = {center: xdim/2., $            ; x center of drawing area
  964.           radius: ydim/2, $                ; Radius 
  965.           size_2: xdim/2., $               ; 1/2 of x xsize
  966.           btndown: 0b, $                   ; 0= not pressed, otherwise is pressed
  967.           pt0: fltarr(3), $                ; Point 0 location
  968.           pt1: fltarr(3), $                ; Point 1 location
  969.           wDraw3D: wDraw3D, $              ; Wdiget draw ID
  970.           xc: xc, $                        ; Translation of the objects (x, y, z)
  971.           yc: yc, $
  972.           zc: zc, $
  973.           ColorTable: colorTable, $        ; Color table to restore when exiting
  974.           annotation: annotation, $        ; Models   
  975.           top3D: top3D, $
  976.           heart: heart, $
  977.           heart_inner: heart_inner, $      ; Heart polygon objects
  978.           heart_outer: heart_outer, $
  979.           heart_bot: heart_bot, $
  980.           WDragLowButton: wDragLowButton, $; Drag quality button IDs
  981.           WDragHiButton: wDragHiButton, $
  982.           WFlatButton: wFlatButton, $      ; Shading button IDs
  983.           WGouraudButton: wGouraudButton, $
  984.           WWireButton: wWireButton, $      ; Style button IDs
  985.           WSolidButton: wSolidButton, $
  986.           WBase: wBase, $                  ; Top level base
  987.           Font18: font18, $
  988.           Font24: font24, $
  989.       f: font24, $     
  990.           Font_sm:font_sm, $
  991.           Font_big:font_big, $
  992.           Title1: title1, $
  993.           Title2: title2, $
  994.           OTrack: oTrack, $                ; Trackball object
  995.           OContainer: oContainer, $        ; Container object
  996.           i_verts: i_verts, $              ; For Inner heart (i-), Outer heart(o_)
  997.           i_polys: i_polys, $              ; and bottom Heart (b_): these are
  998.           i_color: i_color, $              ; the colors, polylines, and 
  999.           o_verts: o_verts, $              ; and vertices arrays
  1000.           o_polys: o_polys, $
  1001.           o_color: o_color, $
  1002.           b_verts: b_verts, $
  1003.           b_polys: b_polys, $
  1004.           b_color: b_color, $
  1005.           lite1_icon: lite1_icon, $        ; Light objects
  1006.           lite2_icon: lite2_icon, $
  1007.           axis_obj: axis_obj, $            ; Axis object
  1008.           current_frame: current_frame, $  ; current frame index
  1009.           OView : oView, $                 ; View object
  1010.           OText : oText, $                 ; Text object
  1011.           OFont : oFont, $                 ; Font object
  1012.           dragq : 0, $                     ; Drag quality (0=low, 1=med., 2=high)
  1013.           OWindow: oWindow, $              ; Window object
  1014.           InitTM: FLTARR(4,4), $           ; Initial transformation
  1015.           groupBase: groupBase $           ; Base of Group Leader
  1016.          }
  1017.  
  1018.     ;  Draw the initial view to the window.
  1019.     ;
  1020.     WIDGET_CONTROL, wBase, SENSITIVE=1
  1021.  
  1022.     WIDGET_CONTROL, wBase, /HOURGLASS
  1023.  
  1024.     top->Remove, oText
  1025.  
  1026.     ;  Start up with an animation.
  1027.     ;
  1028.     WIDGET_CONTROL, state.wBase, SENSITIVE=0
  1029.     i = (state.current_frame + 1) MOD 16
  1030.     for j = 0,15 do begin
  1031.         state.top3D->Rotate, [1,0,0], -1
  1032.         state.top3D->Rotate, [0,1,0], 3
  1033.         state.heart_inner->SetProperty, $
  1034.             DATA=REFORM(state.i_verts(i,*,*))
  1035.         state.heart_outer->SetProperty, $
  1036.             DATA=REFORM(state.o_verts(i,*,*))
  1037.         state.heart_bot->SetProperty, $
  1038.             DATA=REFORM(state.b_verts(i,*,*))
  1039.         state.oWindow->Draw, state.oView
  1040.         i = (i + 1) MOD 16
  1041.     endfor  ;  of  j
  1042.     WIDGET_CONTROL, state.wBase, SENSITIVE=1
  1043.  
  1044.     ;  Get the initial transformation of the top model.
  1045.     ;
  1046.     top3D->GetProperty, TRANSFORM=TM
  1047.     state.initTM = TM
  1048.  
  1049.     WIDGET_CONTROL, wBase, SET_UVALUE=state, /NO_COPY
  1050.  
  1051.     XMANAGER, 'd_heart', wBase,  $
  1052.         CLEANUP='d_heart_Cleanup', /NO_BLOCK
  1053.        
  1054.  
  1055. end         ; Beating Heart
  1056.